package com.microframework.base.core.security.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * 全局安全拦截器
 * 
 * 最高优先级的拦截器，处理所有请求的通用安全逻辑
 */
public class GlobalSecurityInterceptor implements HandlerInterceptor, Ordered {
    
    private static final Logger log = LoggerFactory.getLogger(GlobalSecurityInterceptor.class);
    
    /**
     * 拦截器优先级，值越小优先级越高
     */
    private int order = Ordered.HIGHEST_PRECEDENCE + 100;
    
    /**
     * 是否启用，默认为true
     */
    private boolean enabled = true;
    
    /**
     * 是否输出调试日志，默认为false
     */
    private boolean debug = false;
    
    /**
     * 是否添加安全响应头，默认为true
     */
    private boolean addSecurityHeaders = true;
    
    /**
     * 是否监控慢请求，默认为true
     */
    private boolean monitorSlowRequests = true;
    
    /**
     * 慢请求阈值（毫秒），默认为1000ms
     */
    private long slowRequestThreshold = 1000;
    
    /**
     * 请求处理前的拦截方法
     */
    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
        if (!enabled) {
            return true;
        }
        
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        
        if (debug) {
            log.debug("全局安全拦截器拦截请求: {} {}", method, requestURI);
        }
        
        // 1. 添加安全响应头
        if (addSecurityHeaders) {
            addSecurityHeaders(response);
        }
        
        // 2. 记录请求开始时间
        if (monitorSlowRequests) {
            request.setAttribute("requestStartTime", System.currentTimeMillis());
        }
        
        // 3. 可以在这里添加其他安全逻辑，如CSRF检查、速率限制等
        
        return true;
    }
    
    /**
     * 请求处理后、视图渲染前的拦截方法
     */
    @Override
    public void postHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        if (!enabled) {
            return;
        }
        
        // 可以在这里添加响应处理逻辑
    }
    
    /**
     * 请求完成后的拦截方法
     */
    @Override
    public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, @Nullable Exception ex) throws Exception {
        if (!enabled || !monitorSlowRequests) {
            return;
        }
        
        // 计算请求处理时间
        Long startTime = (Long) request.getAttribute("requestStartTime");
        if (startTime != null) {
            long duration = System.currentTimeMillis() - startTime;
            
            String requestURI = request.getRequestURI();
            int status = response.getStatus();
            
            if (debug) {
                log.debug("请求完成: {} {}, 状态: {}, 耗时: {}ms", 
                        request.getMethod(), requestURI, status, duration);
            }
            
            // 对于慢请求进行日志记录
            if (duration > slowRequestThreshold) {
                log.warn("慢请求: {} {}, 状态: {}, 耗时: {}ms", 
                        request.getMethod(), requestURI, status, duration);
            }
        }
    }
    
    /**
     * 添加安全响应头
     */
    private void addSecurityHeaders(HttpServletResponse response) {
        // 防止点击劫持
        response.setHeader("X-Frame-Options", "DENY");
        
        // 开启XSS防护
        response.setHeader("X-XSS-Protection", "1; mode=block");
        
        // 禁止浏览器猜测内容类型
        response.setHeader("X-Content-Type-Options", "nosniff");
        
        // 内容安全策略
        response.setHeader("Content-Security-Policy", 
                "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; " +
                "style-src 'self' 'unsafe-inline'; img-src 'self' data:; " +
                "connect-src 'self'; font-src 'self' data:; frame-src 'self'; " +
                "object-src 'none'; media-src 'self'");
        
        // 引用策略
        response.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
        
        // 特性策略
        response.setHeader("Permissions-Policy", 
                "camera=(), microphone=(), geolocation=(), payment=()");
    }
    
    /**
     * 获取拦截器优先级
     */
    @Override
    public int getOrder() {
        return order;
    }
    
    /**
     * 设置拦截器优先级
     */
    public void setOrder(int order) {
        this.order = order;
    }
    
    /**
     * 是否启用拦截器
     */
    public boolean isEnabled() {
        return enabled;
    }
    
    /**
     * 设置是否启用拦截器
     */
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
    
    /**
     * 是否输出调试日志
     */
    public boolean isDebug() {
        return debug;
    }
    
    /**
     * 设置是否输出调试日志
     */
    public void setDebug(boolean debug) {
        this.debug = debug;
    }
    
    /**
     * 是否添加安全响应头
     */
    public boolean isAddSecurityHeaders() {
        return addSecurityHeaders;
    }
    
    /**
     * 设置是否添加安全响应头
     */
    public void setAddSecurityHeaders(boolean addSecurityHeaders) {
        this.addSecurityHeaders = addSecurityHeaders;
    }
    
    /**
     * 是否监控慢请求
     */
    public boolean isMonitorSlowRequests() {
        return monitorSlowRequests;
    }
    
    /**
     * 设置是否监控慢请求
     */
    public void setMonitorSlowRequests(boolean monitorSlowRequests) {
        this.monitorSlowRequests = monitorSlowRequests;
    }
    
    /**
     * 获取慢请求阈值
     */
    public long getSlowRequestThreshold() {
        return slowRequestThreshold;
    }
    
    /**
     * 设置慢请求阈值
     */
    public void setSlowRequestThreshold(long slowRequestThreshold) {
        this.slowRequestThreshold = slowRequestThreshold;
    }
} 